package com.cgy.utils.elasticsearch.ql;

import java.util.List;
import java.util.Map;
import java.util.Objects;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.ScoreSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;

import com.cgy.utils.base.strings.StringHelper;
import com.cgy.utils.elasticsearch.condition.Condition;

/**
 * elastic 语句
 * 
 * @author CH
 */
public class ElasticQLHelper {

	private static final String TIMESTAMP = "timestamp";
	private static final String[] SIGNS = new String[] { "[", "]", "(", ")" };

	private static final long DAY = 60 * 60 * 24;

	/**
	 * 获取elastic语句
	 * 
	 * @param condition
	 * @return
	 */
	public static QueryBuilder generateQueryByTime(String timeField, long startTime, long endTime) {
		if (StringUtils.isBlank(timeField)) {
			return null;
		}

		if (endTime <= startTime || endTime <= 0L || endTime > System.currentTimeMillis() / 1000) {
			endTime = System.currentTimeMillis() / 1000;
		}
		if (startTime < 0L || startTime >= endTime) {
			startTime = endTime - DAY;
		}

		RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(timeField);
		rangeQueryBuilder.gte(startTime).lte(endTime);
		return rangeQueryBuilder;
	}

	/**
	 * 获取elastic语句
	 * 
	 * @param condition
	 * @return
	 */
	public static QueryBuilder generateQueryByFields(Condition condition) {
		List<String> fields = condition.getFields();
		Map<String, Object> fieldsAndValue = condition.getFieldsAndValue();
		if (null == fieldsAndValue) {
			return null;
		}

		BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

		String key, valueString = null;
		Object value;
		for (Map.Entry<String, Object> entry : fieldsAndValue.entrySet()) {
			key = entry.getKey();
			value = entry.getValue();
			if (Objects.nonNull(value)) {
				valueString = value.toString();
			}
			if (StringHelper.firstAndEndContains(valueString, SIGNS)) {
				QueryBuilder generateQueryMatchByRange = generateQueryMatchByRange(key, valueString);
				if(null != generateQueryMatchByRange) {
					boolQuery.must(generateQueryMatchByRange);
				}
			} else if (valueString.contains("*")) {
				QueryBuilder generateQueryWildByFields = generateQueryWildByFields(key, valueString);
				if(null != generateQueryWildByFields) {
					boolQuery.should(generateQueryWildByFields);
				}
			} else {
				QueryBuilder generateQueryMatchByFields = generateQueryMatchByFields(key, value);
				if(null != generateQueryMatchByFields) {
					boolQuery.must(generateQueryMatchByFields);
				}
			}

		}

		return boolQuery;
	}

	/**
	 * 模糊匹配
	 * 
	 * @return
	 */
	public static QueryBuilder generateQueryWildByFields(String key, String value) {
		if (!StringUtils.isAllBlank(key, value) && value.contains("*")) {
			return QueryBuilders.wildcardQuery(key + ".keyword", value);
		}
		return null;
	}

	/**
	 * 分词模糊匹配
	 * 
	 * @return
	 */
	public static QueryBuilder generateQueryIKByFields(String key, String value) {
		if (!StringUtils.isAllBlank(key, value) && value.contains("*")) {
			return QueryBuilders.wildcardQuery(key + ".keyword", value);
		}
		return null;
	}

	/**
	 * 模糊匹配
	 * 
	 * @return
	 */
	public static QueryBuilder generateQueryRegexpByFields(String key, String value) {
		if (!StringUtils.isAllBlank(key, value) && StringHelper.firstOrEndContains(value, "*")) {
			return QueryBuilders.regexpQuery(key, value);
		}
		return null;
	}

	/**
	 * 字段匹配
	 * 
	 * @return
	 */
	public static QueryBuilder generateQueryMatchByFields(String key, Object value) {
		if (!StringUtils.isAllBlank(key) && null != value && !"".equals(value.toString())) {
			return QueryBuilders.matchPhraseQuery(key, value);
		}
		return null;
	}

	/**
	 * 区间匹配
	 * 
	 * @return
	 */
	public static QueryBuilder generateQueryMatchByRange(String key, String value) {
		if (!StringUtils.isAllBlank(key, value) && StringHelper.firstAndEndContains(value, SIGNS)) {
			String newValue = value.substring(1, value.length() - 1);
			if (StringUtils.isBlank(newValue)) {
				return null;
			}
			String[] split = newValue.split(",");
			if (split.length == 0) {
				return null;
			}
			String first = value.substring(0, 1);
			String end = value.substring(value.length() - 1);
			String firstValue = split[0];
			String endValue = split[1];
			
			firstValue = firstValue.trim();
			endValue = endValue.trim();

			if (NumberUtils.isCreatable(firstValue) && NumberUtils.isCreatable(endValue)) {
				 long start = Long.valueOf(firstValue);
				 long ends = Long.valueOf(endValue);
				 if(firstValue.length() == 10 && endValue.length() == 0) {
					 return generateQueryByTime(key, start, ends);
				 }
				 RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery(key);
					if ("[".equals(first)) {
						rangeQuery.gte(start);
					} else if ("(".equals(first)) {
						rangeQuery.gt(start);
					}
					if ("]".equals(end)) {
						rangeQuery.lte(ends);
					} else if (")".equals(first)) {
						rangeQuery.lt(ends);
					}

					return rangeQuery;
				 
			}

		}
		return null;
	}

	/**
	 * 获取elastic语句
	 * 
	 * @param level
	 * @param messageKey
	 * @param startTime
	 * @param endTime
	 * @return
	 */
	public static QueryBuilder generateQuery(String level, String messageKey, Long startTime, Long endTime) {
		// term query(检索level)
		TermQueryBuilder levelQuery = null;
		if (StringUtils.isNotBlank(level)) {
			levelQuery = QueryBuilders.termQuery("level", level.toLowerCase());
		}
		// match query(检索message)
		MatchQueryBuilder messageQuery = null;
		if (StringUtils.isNotBlank(messageKey)) {
			messageQuery = QueryBuilders.matchQuery("message", messageKey);
		}
		// range query(检索timestamp)
		RangeQueryBuilder timeQuery = QueryBuilders.rangeQuery(TIMESTAMP);
		timeQuery.format("epoch_millis");
		if (Objects.isNull(startTime)) {
			if (Objects.isNull(endTime)) {
				timeQuery = null;
			} else {
				timeQuery.lte(endTime);
			}
		} else {
			if (Objects.isNull(endTime)) {
				timeQuery.gte(startTime);
			} else {
				timeQuery.gte(startTime).lte(endTime);
			}
		}
		// 将上述三个query组合
		BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
		if (Objects.nonNull(levelQuery)) {
			boolQuery.must(levelQuery);
		}
		if (Objects.nonNull(messageQuery)) {
			boolQuery.must(messageQuery);
		}
		if (Objects.nonNull(timeQuery)) {
			boolQuery.must(timeQuery);
		}
		return boolQuery;
	}

	/**
	 * 字段排序
	 * 
	 * @param condition
	 * @return
	 */
	public static FieldSortBuilder generateFieldSort(Condition condition) {
		if (StringUtils.isNotBlank(condition.getSortFields())) {
			return SortBuilders.fieldSort(condition.getSortFields()).order(condition.getSortOrder());
		} else {
			return null;
		}
	}

	/**
	 * 排序
	 * 
	 * @param condition
	 * @return
	 */
	public static ScoreSortBuilder generateScoreSort(Condition condition) {
		return SortBuilders.scoreSort().order(condition.getSortOrder());
	}

}
